﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace LiJu.Common
{
    public class DDKBatch
    {
        //线程 用于监听服务端 发来的消息
        private static Thread th;
        //客户端对象
        private static TcpClient tcpclient;
        //创建 循环发送线程
        private static Thread thread = null;
        //电批IP
        private static string IP = null;
        //电批端口号
        private static int Port;
        /// <summary>
        /// 连接状态,NUll->未连接，包含有错误则连接失败，有连接成功则正确
        /// </summary>
        public static string ConnectionState;

        /// <summary>
        /// ddk电批状态
        /// 0:正常 1:指令错误(NAK) 2:忙碌(BUSY) 3:异常(BYPASS)
        /// </summary>
        public static int ddkState = 0;
        /// <summary>
        /// 是否启动 连接了
        /// </summary>
        public static bool isMonitor = false;
        /// <summary>
        /// 读取参数前面的值
        /// </summary>
        private static byte[] readParam;

        /// <summary>
        /// 扭紧类型
        /// 0：扭矩法 1：角度法
        /// </summary>
        private static int screwUpType = 0;

        /// <summary>
        /// 曲线类型
        /// 00：0.5deg扭矩
        /// 10：0.5电流扭矩
        /// 20：10mec扭矩
        /// 30：10mec电流
        /// </summary>
        public static int curveType = 0;
        /// <summary>
        /// 曲线基准：角度基准，时间基准
        /// </summary>
        public static int curveDatum = 0;
        /// <summary>
        /// y轴曲线数据
        /// </summary>
        public static List<double> yValueList = new List<double>();
        /// <summary>
        /// x轴曲线数据
        /// </summary>
        public static List<double> xValueList = new List<double>();
        /// <summary>
        /// 曲线有效数据
        /// </summary>
        public static List<double> y2ValueList = new List<double>();
        /// <summary>
        /// 拧紧结果
        /// </summary>
        public static bool screwUpResult = false;

        /// <summary>
        /// 最大扭矩
        /// </summary>
        public static double maxTorque = 0;

        /// <summary>
        /// 最终扭矩
        /// </summary>
        public static double lastTorque = 0;

        /// <summary>
        /// 最终角度
        /// </summary>
        public static double lastAngle = 0;

        /// <summary>
        /// 最大扭矩时角度
        /// </summary>
        public static double lastAngleWhenMaxTorque = 0;

        /// <summary>
        /// 拧紧参数对象
        /// </summary>
        public static ScrewParam screwParam = new ScrewParam();

        /// <summary>
        /// 扭矩类型
        /// </summary>
        public static List<string> TighteningTypeList = new List<string>() { "扭矩法", "角度法" };

        /// <summary>
        /// 保存曲线结果
        /// </summary>
        public static Action<int,double, List<double>> SaveCurveAction;

        /// <summary>
        /// 电批参数返回
        /// </summary>
        public static Action<ScrewParam> ScrewParamReturnAction;

        /// <summary>
        /// 拧紧结果返回
        /// </summary>
        public static Action<int, double, double> ScrewResultAction;

        public static ScrewResult ScrewResult;

        #region 电批参数
        /// <summary>
        /// 全量程扭矩
        /// </summary>
        public static double allRangeTorque = 0;


        /// <summary>
        /// 最大扭矩下限
        /// </summary>
        public static double maxTorqueLowLimit = 0;

        /// <summary>
        /// 最大扭矩上限
        /// </summary>
        public static double maxTorqueUpLimit = 0;

        /// <summary>
        /// 目标扭矩
        /// </summary>
        public static double targetTorque = 0;

        /// <summary>
        /// 开始减速扭矩
        /// </summary>
        public static double slowTorque = 0;

        /// <summary>
        /// 1ST扭矩
        /// </summary>
        public static double firstTorque = 0;

        /// <summary>
        /// SNUG扭矩
        /// </summary>
        public static double sungTorque = 0;

        /// <summary>
        /// 2ND扭矩
        /// </summary>
        public static double secendTorque = 0;

        /// <summary>
        /// 最終扭矩下限
        /// </summary>
        public static double lastTorqueLowlimit = 0;

        /// <summary>
        /// 最終扭矩上限
        /// </summary>
        public static double lastTorqueUplimit = 0;

        /// <summary>
        /// 1ST角度
        /// </summary>
        public static double firstAngle = 0;

        /// <summary>
        /// 2ND角度
        /// </summary>
        public static double secendAngle = 0;

        /// <summary>
        /// 起始时间
        /// </summary>
        public static double startTime = 0;

        /// <summary>
        /// 初期速度
        /// </summary>
        public static double startSpeed = 0;


        /// <summary>
        /// 空转速度
        /// </summary>
        public static double noTorqueSpeed = 0;

        /// <summary>
        /// 1st速度
        /// </summary>
        public static double fisrtSpeed = 0;


        /// <summary>
        /// 2nd速度
        /// </summary>
        public static double secendSpeed = 0;


        /// <summary>
        /// 3rd速度
        /// </summary>
        public static double thirdSpeed = 0;

        /// <summary>
        /// 反转速度
        /// </summary>
        public static double reverseSpeed = 0;

        /// <summary>
        /// 1ST时间上限
        /// </summary>
        public static double firstTimeUpLimit = 0;


        /// <summary>
        /// 2ND时间上限
        /// </summary>
        public static double secendTimeUpLimit = 0;


        /// <summary>
        /// 目標角度
        /// </summary>
        public static double targeAngle = 0;

        /// <summary>
        /// 最終角度下限
        /// </summary>
        public static double lastAngleLowlimit = 0;

        /// <summary>
        /// 最終角度上限
        /// </summary>
        public static double lastAngleUplimit = 0;
        #endregion


        /// <summary>
        /// 替换字符串字符
        /// </summary>
        /// <param name="original"></param>
        /// <param name="startIndex"></param>
        /// <param name="length"></param>
        /// <param name="replacement"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static string ReplaceIndexRange(string original, int startIndex, int length, string replacement)
        {
            if (startIndex < 0 || startIndex >= original.Length)
                throw new ArgumentOutOfRangeException(nameof(startIndex));

            if (length < 0 || length > original.Length - startIndex)
                throw new ArgumentOutOfRangeException(nameof(length));

            return original.Remove(startIndex, length).Insert(startIndex, replacement);
        }
        /// <summary>
        /// 字符串转字节数组
        /// </summary>
        /// <param name="textdata"></param>
        /// <returns></returns>
        private static byte[] Transformation(string textdata)
        {
            byte[] data = null;

            string[] HexStr = textdata.Trim().Split(' ');
            data = new byte[HexStr.Length];
            for (int i = 0; i < HexStr.Length; i++)
            {
                data[i] = (byte)(Convert.ToInt32(HexStr[i], 16));
            }
            return data;
        }

        /// <summary>
        ///  字符串两个字符后加空格
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static string AddSpaceEveryTwoChars(string input)
        {
            if (input == null)
                throw new ArgumentNullException(nameof(input));

            if (input.Length <= 2)
                return input + " ";

            StringBuilder result = new StringBuilder();
            for (int i = 0; i < input.Length; i++)
            {
                result.Append(input[i]);
                if (i % 2 == 1)
                    result.Append(' ');
            }
            //result.Append(input.Substring(input.Length - 2));
            return result.ToString();
        }

        /// <summary>
        /// 网口连接
        /// </summary>
        /// <param name="ipaddress">IP地址</param>
        /// <param name="ipport">端口</param>
        public static void Connection(string ipaddress, int ipport)
        {
            //InitDataTableData();//测试用
            //判断是否连接了
            if (isMonitor == false)
            {
                try
                {
                    //创建客户端对象 初始化
                    tcpclient = new TcpClient();
                    //连接服务端
                    tcpclient.Connect(ipaddress, ipport);
                    //初始化 监听服务端回传消息 线程
                    th = new Thread(Recive);
                    //设置 后台线程
                    th.IsBackground = true;
                    //启动线程 传递对象
                    th.Start(tcpclient);
                    IP = ipaddress;
                    Port = ipport;
                    //启动监听
                    isMonitor = true;
                    ConnectionState = "连接成功";
                    Debug.WriteLine("ConnectionState->" + ConnectionState);
                }
                catch (Exception ex)
                {
                    ConnectionState = "错误" + ex.Message.ToString();
                    Debug.WriteLine("ConnectionState->" + ConnectionState);
                }
            }
            else
            {
                //关闭监听
                tcpclient.Close();
                try
                {
                    if (thread != null)
                    {
                        thread.Abort();
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"关闭监听和接收线程->{ex.Message}");
                }
                isMonitor = false;

            }
        }

        /// <summary>
        /// 网口连接
        /// </summary>
        /// <param name="ipaddress">IP地址</param>
        /// <param name="ipport">端口</param>
        public static void Connection()
        {
            string ipaddress = "192.168.11.10";
            int ipport = 23;
            //InitDataTableData();//测试用
            //判断是否连接了
            if (isMonitor == false)
            {
                try
                {
                    //创建客户端对象 初始化
                    tcpclient = new TcpClient();
                    //连接服务端
                    tcpclient.Connect(ipaddress, ipport);
                    //初始化 监听服务端回传消息 线程
                    th = new Thread(Recive);
                    //设置 后台线程
                    th.IsBackground = true;
                    //启动线程 传递对象
                    th.Start(tcpclient);
                    IP = ipaddress;
                    Port = ipport;
                    //启动监听
                    isMonitor = true;
                    ConnectionState = "连接成功";
                    Debug.WriteLine("ConnectionState->" + ConnectionState);
                }
                catch (Exception ex)
                {
                    ConnectionState = "错误" + ex.Message.ToString();
                    Debug.WriteLine("ConnectionState->" + ConnectionState);
                }
            }
            else
            {
                //关闭监听
                tcpclient.Close();
                try
                {
                    if (thread != null)
                    {
                        thread.Abort();
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"关闭监听和接收线程->{ex.Message}");
                }
                isMonitor = false;

            }
        }

        /// <summary>
        /// 重新连接
        /// </summary>
        private static void ReConnect()
        {
            try
            {
                if(tcpclient != null )
                {
                    //连接服务端
                    tcpclient.Connect(IP, Port);
                    //初始化 监听服务端回传消息 线程
                    th = new Thread(Recive);
                    //设置 后台线程
                    th.IsBackground = true;
                    //启动线程 传递对象
                    th.Start(tcpclient);
                    //启动监听
                    isMonitor = true;
                    ConnectionState = "重连成功";
                }

            }
            catch (Exception ex)
            {
                isMonitor = false;
                Debug.WriteLine("重连失败->" + ex.Message);
            }
        }

        /// <summary>
        /// 网口发送
        /// </summary>
        /// <param name="data"></param>
        public static void SendOut(string data)
        {
            try
            {
                byte[] _jytbyte = Transformation(data); //System.Text.Encoding.Default.GetBytes(data);
                if (tcpclient != null && tcpclient.Connected)
                {
                    tcpclient.GetStream().Write(_jytbyte, 0, _jytbyte.Length);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"发送错误->{ex.Message}");
                if (tcpclient != null && tcpclient.Connected==false)
                {
                    ReConnect();
                    //重新发送
                    try
                    {  
                        byte[] _jytbyte = Transformation(data); //System.Text.Encoding.Default.GetBytes(data);
                        if (tcpclient != null && tcpclient.Connected)
                        {
                            tcpclient.GetStream().Write(_jytbyte, 0, _jytbyte.Length);
                        }
                    }
                    catch (Exception)
                    {
                        Debug.WriteLine($"重发失败->{ex.Message}");
                    }

                }               
            }
        }

        /// <summary>
        /// 网口接收
        /// </summary>
        /// <param name="client"></param>
        private static void Recive(object client)
        {
            NetworkStream reciveStream = ((TcpClient)client).GetStream();
            while (true)
            {
                try
                {
                    //NetworkStream nss = ((TcpClient)client).GetStream();
                    byte[] recData = new byte[1024 * 1024];//存储服务端发送过来的数据
                    int _length = reciveStream.Read(recData, 0, recData.Length);
                    if (_length > 0)
                    {
                        //string msg = Encoding.Default.GetString(recData, 0, _length);
                        //byte[] data= System.Text.Encoding.Default.GetBytes(msg);
                        StringBuilder sb = new StringBuilder();
                        for (int i = 0; i < _length; i++)
                        {
                            sb.AppendFormat("{0:x2}" + " ", recData[i]);
                        }
                        Debug.WriteLine(sb.ToString().ToUpper());
                        if (recData[0] == 0xFD  && recData[4] == 0x15)
                        {
                            ddkState = 1;
                        }
                        else if (recData[0] == 0xFD && recData[4] == 0x16)
                        {
                            ddkState = 2;
                        }
                        else if (recData[0] == 0xFD && recData[4] == 0x18)
                        {
                            ddkState = 3;
                        }

                        #region 读取拧紧参数
                        if (recData[0] == 0xFD && recData[3] == 0xA1 && recData[4] == 0x06)
                        {
                            StringBuilder strA1 = new StringBuilder();
                            for (int i = 0; i < _length; i++)
                            {
                                strA1.AppendFormat("{0:X2}" + " ", recData[i]);
                            }
                            if (!isFirst)
                                dicA1.Add((int)recData[5], strA1);

                            readParam = recData.Skip(6).Take(1023).ToArray();
                            screwParam = new ScrewParam();

                            //工具型号
                            if (recData[8] == 0x01)
                            {
                                screwParam.ToolType = ToolTypeList[0];
                            }
                            else if (recData[8] == 0x03)
                            {
                                screwParam.ToolType = ToolTypeList[1];
                            }

                            //拧紧方式
                            if (recData[16] == 0x00)
                            {
                                screwUpType = 0;
                                screwParam.tighteningType = TighteningTypeList[0];
                                Debug.WriteLine("扭矩法");
                            }
                            else if (recData[16] == 0x01)
                            {
                                screwUpType = 1;
                                screwParam.tighteningType = TighteningTypeList[1];
                                Debug.WriteLine("角度法");
                            }
    
                            //参数序号
                            screwParam.taskId = (int)recData[5];

                            //全量程扭矩
                            string tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(40).Take(4).ToArray());
                            screwParam.allRangeTorque = Convert.ToInt32(tempValueStr) / 10000.0f;

                            //最大扭矩下限
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(44).Take(4).ToArray());
                            screwParam.maxTorqueLowLimit = Convert.ToInt32(tempValueStr) / 10000.0f;

                            //最大扭矩上限
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(48).Take(4).ToArray());
                            screwParam.maxTorqueUpLimit = Convert.ToInt32(tempValueStr) / 10000.0f;

                            //目标扭矩
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(52).Take(4).ToArray());
                            screwParam.targetTorque = Convert.ToInt32(tempValueStr) / 10000.0f;

                            //开始减速扭矩
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(56).Take(4).ToArray());
                            screwParam.slowTorque = Convert.ToInt32(tempValueStr) / 10000.0f;

                            //1ST扭矩
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(60).Take(4).ToArray());
                            screwParam.firstTorque = Convert.ToInt32(tempValueStr) / 10000.0f;

                            //SNUG扭矩
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(68).Take(4).ToArray());
                            screwParam.sungTorque = Convert.ToInt32(tempValueStr) / 10000.0f;

                            //2ND扭矩
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(76).Take(4).ToArray());
                            screwParam.secendTorque = Convert.ToInt32(tempValueStr) / 10000.0f;


                            //最終扭矩下限
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(112).Take(4).ToArray());
                            screwParam.lastTorqueLowlimit = Convert.ToInt32(tempValueStr) / 10000.0f;

                            //最終扭矩上限
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(116).Take(4).ToArray());
                            screwParam.lastTorqueUplimit = Convert.ToInt32(tempValueStr) / 10000.0f;

                            //1ST角度
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(140).Take(4).ToArray());
                            screwParam.firstAngle = Convert.ToInt32(tempValueStr) / 1000.0f;

                            //2ND角度
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(144).Take(4).ToArray());
                            screwParam.secendAngle = Convert.ToInt32(tempValueStr) / 1000.0f;

                            //起始时间
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(208).Take(4).ToArray());
                            screwParam.startTime = Convert.ToInt32(tempValueStr) / 1000.0f;

                            //初期速度
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(252).Take(4).ToArray());
                            screwParam.startSpeed = Convert.ToInt32(tempValueStr) / 100.0f;


                            //空转速度
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(256).Take(4).ToArray());
                            screwParam.noTorqueSpeed = Convert.ToInt32(tempValueStr) / 100.0f;

                            //1st速度
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(260).Take(4).ToArray());
                            screwParam.firstSpeed = Convert.ToInt32(tempValueStr) / 100.0f;


                            //2nd速度
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(264).Take(4).ToArray());
                            screwParam.secendSpeed = Convert.ToInt32(tempValueStr) / 100.0f;


                            //3rd速度
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(268).Take(4).ToArray());
                            screwParam.thirdSpeed = Convert.ToInt32(tempValueStr) / 100.0f;

                            //反转速度
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(276).Take(4).ToArray());
                            screwParam.reverseSpeed = Convert.ToInt32(tempValueStr) / 100.0f;

                            //1ST时间上限
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(216).Take(4).ToArray());
                            screwParam.firstTimeUpLimit = Convert.ToInt32(tempValueStr) / 1000.0f;


                            //2ND时间上限
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(224).Take(4).ToArray());
                            screwParam.secendTimeUpLimit = Convert.ToInt32(tempValueStr) / 1000.0f;


                            //目標角度
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(136).Take(4).ToArray());
                            screwParam.targeAngle = Convert.ToInt32(tempValueStr) / 1000.0f;

                            //最終角度下限
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(128).Take(4).ToArray());
                            screwParam.lastAngleLowlimit = Convert.ToInt32(tempValueStr) / 1000.0f;

                            //最終角度上限
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(132).Take(4).ToArray());
                            screwParam.lastAngleUplimit = Convert.ToInt32(tempValueStr) / 1000.0f;

                            //参数名
                            //List<byte> namebytes = new List<byte>();
                            //for (int i = 0; i < 32; i++)
                            //{
                            //    if (recData[996 + i] == 0x00 || recData[996 + i] == 0x20)
                            //    {
                            //        break;
                            //    }
                            //    namebytes.Add(recData[996 + i]);
                            //}
                            //if (namebytes.Count > 0)
                            //{
                            //    screwParam.name = Encoding.UTF8.GetString(namebytes.ToArray());
                            //}
                            screwParam.name = screwUpType == 1 ? $"{screwParam.targeAngle}D" : $"{screwParam.targetTorque}N";

                            ScrewParamReturnAction?.Invoke(screwParam);

                        }
                        #endregion

                        #region 读取拧紧结果
                        if (recData[0] == 0xFD && recData[3] == 0xE2 && recData[4] == 0x06)
                        {
                            int result = 0;
                            if (recData[25] == 0x01)//REJECT(NG)
                            {
                                result = 0;
                                screwUpResult = false;
                            }
                            else if (recData[25] == 0x02)//ACCEPT(OK)
                            {
                                result = 1;
                                screwUpResult = true;
                            }
                            else if (recData[25] == 0x04)//ABNORMAL(系统报警)
                            {
                                result = 2;
                                screwUpResult = false;
                            }
                            else if (recData[25] == 0x08)//STOP(紧急停止)
                            {
                                result = 3;
                                screwUpResult = false;
                            }
                            else if (recData[25] == 0x20)//BYPASS(信号中断)
                            {
                                result = 4;
                                screwUpResult = false;
                            }
                            //最大扭矩
                            maxTorque = Convert.ToInt32(DataConventer.byteToHexStrNoSpace(recData.Skip(41).Take(4).ToArray())) / 10000.0f;

                            //最终扭矩
                            string tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(45).Take(4).ToArray());
                            lastTorque = Convert.ToInt32(tempValueStr) / 10000.0f;

                            //最终角度
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(69).Take(4).ToArray());
                            lastAngle = Convert.ToInt32(tempValueStr) / 1000.0f;

                            //最大扭矩时角度
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(129).Take(4).ToArray());
                            lastAngleWhenMaxTorque = Convert.ToInt32(tempValueStr) / 1000.0f;

                            ScrewResult = new ScrewResult();
                            ScrewResult.result = result;
                            ScrewResult.maxTorque = maxTorque;
                            ScrewResult.lastTorque = lastTorque;
                            ScrewResult.lastAngle = lastAngle;
                            ScrewResultAction?.Invoke(result, lastTorque, lastAngle);

                        }
                        #endregion

                        #region 读取曲线
                        if (recData[0] == 0xFD && recData[3] == 0xE3 && recData[4] == 0x06)
                        {
                            xValueList.Clear();
                            yValueList.Clear();
                            double basexStep = 1;
                            //int baseYDot = 200;
                            int curveType = 0;
 

                            //角度基准
                            if (recData[18] == 0x00 || recData[18] == 0x10)
                            {
                                curveType = 0;
                                if (curveDatum == 0)//360
                                {
                                    //baseYDot = 360;
                                }
                                else if (curveDatum == 1)//720
                                {
                                    //baseYDot = 720;
                                }
                                else if (curveDatum == 2)//1080
                                {
                                    //baseYDot = 1080;
                                }
                                else if (curveDatum == 3)//1440
                                {
                                    //baseYDot = 1440;
                                }
                                else if (curveDatum == 4)//2160
                                {
                                    //baseYDot = 2160;
                                }
                                else if (curveDatum == 5)//2880
                                {
                                    //baseYDot = 2880;
                                }
                                else if (curveDatum == 6)//3980
                                {
                                    //baseYDot = 3980;
                                }

                            }
                            //时间基准
                            if (recData[18] == 0x20 || recData[18] == 0x30)
                            {
                                //curveType = 2;
                                curveType = 1;//mod by ming 2024-11-25
                                if (curveDatum == 0)//360
                                {
                                    //baseYDot = 200;
                                }
                                else if (curveDatum == 1)//720
                                {
                                    //baseYDot = 400;
                                }
                                else if (curveDatum == 2)//1080
                                {
                                    //baseYDot = 600;
                                }
                                else if (curveDatum == 3)//1440
                                {
                                    //baseYDot = 800;
                                }
                                else if (curveDatum == 4)//2160
                                {
                                    //baseYDot = 1000;
                                }
                                else if (curveDatum == 5)//2880
                                {
                                    //baseYDot = 2000;
                                }
                                else if (curveDatum == 6)//3980
                                {
                                    //baseYDot = 4000;
                                }
                            }
                            if (curveType == 0)//0.5deg扭矩
                            {
                                basexStep = 0.5;
                            }
                            else if (curveType == 1)//0.5电流扭矩
                            {
                                basexStep = 0.5;
                            }
                            else if (curveType == 2)//10mec扭矩
                            {
                                basexStep = 10;//10mec
                            }
                            else if (curveType == 3)//10mec电流
                            {
                                basexStep = 10;//10mec
                            }
                            //扭矩单位
                            if (recData[6] == 0x00)
                            {
                                //Nm
                            }
                            else if (recData[6] == 0x01)
                            {
                                //kgm
                            }
                            else if (recData[6] == 0x02)
                            {
                                //kgcm
                            }
                            else if (recData[6] == 0x03)
                            {
                                //Ftlbs
                            }
                            else if (recData[6] == 0x04)
                            {
                                //Inlbs
                            }

                            //x值小数点位置
                            int xDotPosition = (int)recData[8];

                            //y值小数点位置
                            int yDotPosition = (int)recData[9];

                            //Y轴最大値
                            string tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(10).Take(4).ToArray());
                            double maxYValue = Convert.ToInt32(tempValueStr) / Math.Pow(10, yDotPosition);

                            //X轴最大値
                            tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(14).Take(4).ToArray());
                            double maxXValue = Convert.ToInt32(tempValueStr) / Math.Pow(10, xDotPosition);

                            for (int i = 0; i < (_length - 20) / 4; i++)
                            {
                                tempValueStr = DataConventer.byteToHexStrNoSpace(recData.Skip(i * 4 + 19).Take(4).ToArray());
                                double yValue = Convert.ToInt32(tempValueStr) / Math.Pow(10, yDotPosition);
                                yValueList.Add(yValue / Math.Pow(10, yDotPosition));
                                xValueList.Add(basexStep * i);
                            }
                            y2ValueList.Clear();
                            for (int i = yValueList.Count - 1; i > 0; i--)
                            {
                                double torqueValue = yValueList[i];
                                y2ValueList.Add(torqueValue);
                                if(torqueValue <= 0&& y2ValueList.Exists(t=>t>0))
                                {
                                    break;
                                }
                            }
                            y2ValueList.Reverse();
                            SaveCurveAction?.Invoke(curveType, basexStep, y2ValueList);
                        }
                        #endregion
                    }
                    else
                    {
                        try
                        {

                            if (((TcpClient)client) != null && ((TcpClient)client).Connected)
                            {
                                // NetworkStream ns = ((TcpClient)client).GetStream();
                                //ns.Close();
                                reciveStream.Close();
                                ((TcpClient)client).Close();
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "错误");
                        }

                    }

                }
                catch
                {
                    th.Abort();

                }
            }
        }

        /// <summary>
        /// 拧紧参数读出
        /// paramNum：拧紧参数序号
        /// </summary>
        public static void ReadScrewUpParameters(int paramNum)
        {
            try
            {
                string cmd = "FD 01 00 A1 00 xx 00 FE";
                string param = paramNum.ToString("X");
                if (param.Length == 1)
                {
                    param = param.PadLeft(2, '0');
                }
                cmd = cmd.Replace("xx", param);
                SendOut(cmd);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
        /// <summary>
        /// 参数字典集合
        /// </summary>
        public static Dictionary<int, StringBuilder> dicA1 = new Dictionary<int, StringBuilder>();
        private static readonly string cmdA1 = "FD 00 01 A1 06";
        private static readonly string cmdA2 = "FD 01 00 A2 00 00";
        public static bool isFirst = true;
        /// <summary>
        /// 工具型号
        /// </summary>
        public static List<string> ToolTypeList = new List<string>() { "101RS1-S", "401RS1-S" };
        /// <summary>
        /// 写入ddk参数
        /// </summary>
        /// <param name="screwParam"></param>
        public static void WriteDDK(ScrewParam screwParam)
        {
            try
            {
                if (dicA1.Count > 0)
                {
                    var strA2 = dicA1[screwParam.taskId];
                    strA2.Replace(cmdA1, cmdA2);
                    //工具型号(101,401)
                    var valueStr = screwParam.ToolType == ToolTypeList[0] ? "00 00 01 00" : "00 00 03 00";
                    strA2.Remove(7 * 3, valueStr.Length).Insert(7 * 3, valueStr);
                    //拧紧方式
                    valueStr = screwParam.tighteningType == TighteningTypeList[0] ? "00 00 00 00" : "01 00 00 00";
                    strA2.Remove(17 * 3, valueStr.Length).Insert(17 * 3, valueStr);
                    //目标角度
                    valueStr = AddSpaceEveryTwoChars((screwParam.targeAngle * 1000).ToString().PadLeft(8, '0'));
                    strA2.Remove(137 * 3, valueStr.Length).Insert(137 * 3, valueStr);
                    //最终角度下限(09 99)
                    valueStr = AddSpaceEveryTwoChars((screwParam.lastAngleLowlimit * 1000).ToString().PadLeft(8, '0'));
                    strA2.Remove(129 * 3, valueStr.Length).Insert(129 * 3, valueStr);
                    //最终角度上限(09 99)
                    valueStr = AddSpaceEveryTwoChars((screwParam.lastAngleUplimit * 1000).ToString().PadLeft(8, '0'));
                    strA2.Remove(133 * 3, valueStr.Length).Insert(133 * 3, valueStr);
                    //目标扭矩
                    valueStr = AddSpaceEveryTwoChars((screwParam.targetTorque * 10000).ToString().PadLeft(8, '0'));
                    strA2.Remove(53 * 3, valueStr.Length).Insert(53 * 3, valueStr);
                    //最大扭矩下限
                    valueStr = AddSpaceEveryTwoChars((screwParam.maxTorqueLowLimit * 10000).ToString().PadLeft(8, '0'));
                    strA2.Remove(45 * 3, valueStr.Length).Insert(45 * 3, valueStr);
                    //最大扭矩上限
                    valueStr = AddSpaceEveryTwoChars((screwParam.maxTorqueUpLimit * 10000).ToString().PadLeft(8, '0'));
                    strA2.Remove(49 * 3, valueStr.Length).Insert(49 * 3, valueStr);
                    //1ST扭矩
                    valueStr = AddSpaceEveryTwoChars((screwParam.firstTorque * 10000).ToString().PadLeft(8, '0'));
                    strA2.Remove(61 * 3, valueStr.Length).Insert(61 * 3, valueStr);
                    //SUNG扭矩
                    valueStr = AddSpaceEveryTwoChars((screwParam.sungTorque * 10000).ToString().PadLeft(8, '0'));
                    strA2.Remove(69 * 3, valueStr.Length).Insert(69 * 3, valueStr);
                    //2ND扭矩
                    valueStr = AddSpaceEveryTwoChars((screwParam.secendTorque * 10000).ToString().PadLeft(8, '0'));
                    strA2.Remove(77 * 3, valueStr.Length).Insert(77 * 3, valueStr);
                    //1ST时间上限
                    valueStr = AddSpaceEveryTwoChars((screwParam.firstTimeUpLimit * 1000).ToString().PadLeft(8, '0'));
                    strA2.Remove(217 * 3, valueStr.Length).Insert(217 * 3, valueStr);
                    //2ND时间上限
                    valueStr = AddSpaceEveryTwoChars((screwParam.secendTimeUpLimit * 1000).ToString().PadLeft(8, '0'));
                    strA2.Remove(225 * 3, valueStr.Length).Insert(225 * 3, valueStr);
                    //1ST速度
                    valueStr = AddSpaceEveryTwoChars((screwParam.firstSpeed * 100).ToString().PadLeft(8, '0'));
                    strA2.Remove(261 * 3, valueStr.Length).Insert(261 * 3, valueStr);
                    //2ND速度
                    valueStr = AddSpaceEveryTwoChars((screwParam.secendSpeed * 100).ToString().PadLeft(8, '0'));
                    strA2.Remove(265 * 3, valueStr.Length).Insert(265 * 3, valueStr);

                    Debug.WriteLine($"写入参数{screwParam.taskId},{strA2.ToString().ToUpper()}");
                    SendOut(strA2.ToString());
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 写入拧紧参数
        /// </summary>
        public static void WriteScrewUpParameters(int paramNum, ScrewParam screwParam)
        {
            try
            {
                string cmd = "FD 01 00 A2 00 01 ";
                string param = paramNum.ToString("X");
                if (param.Length == 1)
                {
                    param = param.PadLeft(2, '0');
                }
                cmd += param;
                readParam[22] = (Byte)(readParam[22] & 0x05);//取消比例1,2,3判定
                cmd += DataConventer.byteToHexStr(readParam);
                cmd += " FE";

                //拧紧方式
                string valueStr = "00 00 00 00";
                if (screwParam.tighteningType== TighteningTypeList[0])
                {
                    cmd = ReplaceIndexRange(cmd, 17 * 3, valueStr.Length, valueStr);
                }
                else if (screwParam.tighteningType == TighteningTypeList[1])
                {
                    valueStr = "01 00 00 00";
                    cmd = ReplaceIndexRange(cmd, 17 * 3, valueStr.Length, valueStr);
                }

                //全量程扭矩
                double paramValue = screwParam.allRangeTorque * 10000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 41 * 3, valueStr.Length, valueStr);

                //最大扭矩下限
                paramValue = screwParam.maxTorqueLowLimit * 10000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 45 * 3, valueStr.Length, valueStr);

                //最大扭矩上限
                paramValue = screwParam.maxTorqueUpLimit * 10000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 49 * 3, valueStr.Length, valueStr);
                //目标扭矩
                paramValue = screwParam.targetTorque * 10000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 53 * 3, valueStr.Length, valueStr);
                //开始减速扭矩
                paramValue = screwParam.slowTorque * 10000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 57 * 3, valueStr.Length, valueStr);
                //1ST扭矩
                paramValue = screwParam.firstTorque * 10000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 61 * 3, valueStr.Length, valueStr);

                ////1ST扭矩上限
                //paramValue = (Convert.ToDouble(txt1stTorque.Text.Trim()) + 0.2) * 10000;
                //valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                //cmd = ReplaceIndexRange(cmd, 65 * 3, valueStr.Length, valueStr);
                //SNUG扭矩
                paramValue = screwParam.sungTorque * 10000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 69 * 3, valueStr.Length, valueStr);
                ////SNUG扭矩上限
                //paramValue = (Convert.ToDouble(txtSUNGTorque.Text.Trim()) + 0.2) * 10000;
                //valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                //cmd = ReplaceIndexRange(cmd, 73 * 3, valueStr.Length, valueStr);
                //2ND扭矩
                paramValue = screwParam.secendTorque * 10000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 77 * 3, valueStr.Length, valueStr);
                ////反转扭矩上限
                //valueStr = "00 10 00 00";
                //cmd = ReplaceIndexRange(cmd, 81 * 3, valueStr.Length, valueStr);
                ////起動扭矩断开上限
                //valueStr = "00 10 00 00";
                //cmd = ReplaceIndexRange(cmd, 85 * 3, valueStr.Length, valueStr);
                //比率1开始扭矩 89
                //比率1结束扭矩 93
                //比率2开始扭矩 97
                //比率2结束扭矩 101
                //比率3开始扭矩 105
                //比率3结束扭矩 109

                //最終扭矩下限
                paramValue = screwParam.lastTorqueLowlimit * 10000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 113 * 3, valueStr.Length, valueStr);
                //最終扭矩下上限
                paramValue = screwParam.lastTorqueUplimit * 10000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 117 * 3, valueStr.Length, valueStr);
                //套筒粘合防止反转扭矩制限値
                //空き
                //最終角度下限
                paramValue = screwParam.lastAngleLowlimit * 1000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 129 * 3, valueStr.Length, valueStr);
                //最終角度上限
                paramValue = screwParam.lastAngleUplimit * 1000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 133 * 3, valueStr.Length, valueStr);
                //目標角度
                paramValue = screwParam.targeAngle * 1000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 137 * 3, valueStr.Length, valueStr);
                //1ST角度
                paramValue = screwParam.firstAngle * 1000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 141 * 3, valueStr.Length, valueStr);
                //2ND角度
                paramValue = screwParam.secendAngle * 1000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 145 * 3, valueStr.Length, valueStr);
                //起動扭矩断开角度
                //DIFF+角度
                //DIFF-角度
                //比率1开始角度
                //比率1结束角度
                //比率2开始角度
                //比率2结束角度
                //比率3开始角度
                //比率3结束角度

                //比率1下限
                //比率1上限
                //比率2下限
                //比率2上限
                //比率3下限
                //比率3上限

                //初期時間
                paramValue = screwParam.startTime * 1000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 209 * 3, valueStr.Length, valueStr);
                //1ST時間下限(*1)
                //1ST時間上限(*1)
                paramValue = screwParam.firstTimeUpLimit* 1000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 217 * 3, valueStr.Length, valueStr);
                //2ND時間下限(*1)
                //2ND時間上限(*1)
                paramValue = screwParam.secendTorque * 1000;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 225 * 3, valueStr.Length, valueStr);

                //扭矩保持時間
                //拧紧前反转的等待
                //反转初期時間
                //加速時間
                //減速時間
                //無負荷時減速時間


                //初期速度
                paramValue = screwParam.startSpeed * 100;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 253 * 3, valueStr.Length, valueStr);
                //无负荷速度
                paramValue = screwParam.noTorqueSpeed * 100;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 257 * 3, valueStr.Length, valueStr);
                //1st速度
                paramValue = screwParam.firstSpeed * 100;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 261 * 3, valueStr.Length, valueStr);
                //2nd速度
                paramValue = screwParam.secendSpeed * 100;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 265 * 3, valueStr.Length, valueStr);
                //3rd速度
                paramValue = screwParam.thirdSpeed * 100;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 269 * 3, valueStr.Length, valueStr);
                //反转初期速度
                //反转1速度
                paramValue = screwParam.reverseSpeed * 100;
                valueStr = AddSpaceEveryTwoChars(paramValue.ToString().PadLeft(8, '0'));
                cmd = ReplaceIndexRange(cmd, 277 * 3, valueStr.Length, valueStr);
                //反转2速度
                //反转3速度
                //偏置检查速度
                //无负荷 螺纹牙数
                //反转2螺纹牙数
                //反转3螺纹牙数
                //回転螺纹牙数下限
                //回転螺纹牙数上限
                //偏置检查螺纹牙数
                //全量程電流
                //電流上限
                //電流下限
                //電流制限
                //套筒粘合防止反转時間
                //最終減速時間
                //1ST,2ND時間上下限増加桁数
                //補正角度
                //共回り検知角度
                //角度上限
                //反转加速時間
                //参数名保存
                if (!string.IsNullOrEmpty(screwParam.name.Trim()))
                {
                    byte[] nameBytes = Encoding.UTF8.GetBytes(screwParam.name.Trim());
                    valueStr = DataConventer.byteToHexStrFirstNoSpace(nameBytes);
                    cmd = ReplaceIndexRange(cmd, 997 * 3, valueStr.Length, valueStr);
                }

                //DAMY
                //byte[] bytes = Transformation(cmd);

                SendOut(cmd);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
        /// <summary>
        /// 读取曲线
        /// </summary>
        public static void ReadCurve(int fmt,int range)
        {
            try
            {
                string cmd = "FD 00 01 E3 00 yy zz FE";
                string type = null;
                if (fmt == 0)//0.5deg扭矩
                {
                    type = "00";
                }
                else if (fmt == 1)//0.5电流扭矩
                {
                    type = "10";
                }
                else if (fmt == 2)//10mec扭矩
                {
                    type = "20";
                }
                else if (fmt == 3)//10mec电流
                {
                    type = "30";
                }
                cmd = cmd.Replace("yy", type);

                string dot = null;
                //deg,time点数
                if (range == 0)//360,200
                {
                    dot = "00";
                }
                else if (range == 1)//720,400
                {
                    dot = "01";
                }
                else if (range == 2)//1080,600
                {
                    dot = "02";
                }
                else if (range == 3)//1440,800
                {
                    dot = "03";
                }
                else if (range == 4)//2160,1000
                {
                    dot = "04";
                }
                else if (range == 5)//2880,2000
                {
                    dot = "05";
                }
                else if (range == 6)//3980,4000
                {
                    dot = "06";
                }
                cmd = cmd.Replace("zz", dot);
                SendOut(cmd);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 读取电批状态
        /// </summary>
        /// <returns></returns>
        public static bool ReadDDKState()
        {
            if (tcpclient != null && tcpclient.Connected == false)
            {
                return false;
            }
            else
            {
                try
                {
                    //打开远程设置
                    string cmd = "FD 01 00 F4 00 01 00 FE";
                    SendOut(cmd);
                    Thread.Sleep(200);
                    if(ddkState==0)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }

                }
                catch (Exception)
                {
                    return false;
                }
            }
        }

        /// <summary>
        /// 读取返回结果
        /// </summary>
        public static ScrewResult ReadScrewResult()
        {
            try
            {
                string cmd = "FD 00 01 E2 00 FE";
                SendOut(cmd);
                Thread.Sleep(300);
                return ScrewResult;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }
    }

    public class ScrewParam
    {
        /// <summary>
        /// 任务号
        /// </summary>
        public int taskId { get; set; }
        /// <summary>
        /// 参数名称
        /// </summary>
        public string name { get; set; }
        /// <summary>
        /// 工具型号
        /// </summary>
        public string ToolType { get; set; }
        /// <summary>
        /// 扭紧类型 0:扭矩法 1:角度法
        /// </summary>
        public string tighteningType { get; set; }

        /// <summary>
        /// 全量程扭矩
        /// </summary>
        public double allRangeTorque { get; set; } = 10.0;

        /// <summary>
        /// 最大扭矩下限
        /// </summary>
        public double maxTorqueLowLimit { get; set; }

        /// <summary>
        /// 最大扭矩上限
        /// </summary>
        public double maxTorqueUpLimit { get; set; } = 10.0;

        /// <summary>
        /// 目标扭矩
        /// </summary>
        public double targetTorque { get; set; }

        /// <summary>
        /// 开始减速扭矩
        /// </summary>
        public double slowTorque { get; set; }

        /// <summary>
        /// 1ST扭矩
        /// </summary>
        public double firstTorque { get; set; }

        /// <summary>
        /// SNUG扭矩
        /// </summary>
        public double sungTorque { get; set; }

        /// <summary>
        /// 2ND扭矩
        /// </summary>
        public double secendTorque { get; set; }

        /// <summary>
        /// 最終扭矩下限
        /// </summary>
        public double lastTorqueLowlimit { get; set; }

        /// <summary>
        /// 最終扭矩上限
        /// </summary>
        public double lastTorqueUplimit { get; set; } = 10.0;

        /// <summary>
        /// 1ST角度
        /// </summary>
        public double firstAngle { get; set; } = 9999.9;

        /// <summary>
        /// 2ND角度
        /// </summary>
        public double secendAngle { get; set; } = 9999.9;

        /// <summary>
        /// 起始时间
        /// </summary>
        public double startTime { get; set; }

        /// <summary>
        /// 初期速度
        /// </summary>
        public double startSpeed { get; set; } = 30;


        /// <summary>
        /// 空转速度
        /// </summary>
        public double noTorqueSpeed { get; set; } = 30;

        /// <summary>
        /// 1st速度
        /// </summary>
        public double firstSpeed { get; set; } = 30;


        /// <summary>
        /// 2nd速度
        /// </summary>
        public double secendSpeed { get; set; } = 30;


        /// <summary>
        /// 3rd速度
        /// </summary>
        public double thirdSpeed { get; set; } = 30;

        /// <summary>
        /// 反转速度
        /// </summary>
        public double reverseSpeed { get; set; } = 30;

        /// <summary>
        /// 1ST时间上限
        /// </summary>
        public double firstTimeUpLimit { get; set; }


        /// <summary>
        /// 2ND时间上限
        /// </summary>
        public double secendTimeUpLimit { get; set; }


        /// <summary>
        /// 目標角度
        /// </summary>
        public double targeAngle { get; set; }

        /// <summary>
        /// 最終角度下限
        /// </summary>
        public double lastAngleLowlimit { get; set; }

        /// <summary>
        /// 最終角度上限
        /// </summary>
        public double lastAngleUplimit { get; set; } = 9999.9;
    }

    public class ScrewResult
    {
        /// <summary>
        ///  0:REJECT(NG) 1:ACCEPT(OK) 2:ABNORMAL(系统报警) 3:STOP(紧急停止) 4:BYPASS(信号中断) 
        /// </summary>
        public int result { get; set; }

        /// <summary>
        /// 最大扭矩
        /// </summary>
        public double maxTorque { get; set; }

        /// <summary>
        /// 最终扭矩
        /// </summary>
        public double lastTorque { get; set; }

        /// <summary>
        /// 最终角度
        /// </summary>
        public double lastAngle { get; set; }
    }

}
